package com.gali.leetcode.day5;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Auther: gali
 * @Date: 2022/7/18-07-18-20:28
 * @Description:三数之和
 */
public class Solution {
    //给你一个包含 n 个整数的数组 nums，判断 nums 中是否存在三个元素 a，b，c
    // 使得 a + b + c = 0 ？请你找出所有和为 0 且不重复的三元组。
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> lists=new ArrayList<>();
        Arrays.sort(nums);//排序
        int len=nums.length;
        //特殊情况
        if (len<3){
            return lists;
        }
        for (int i = 0; i < len; i++) {
            if (nums[i]>0) return lists;
            if(i > 0 && nums[i] == nums[i-1]) continue;//去重
            int cur=nums[i];
            int left=i+1;
            int right=len-1;
            while (left<right){
                int sum=cur+nums[left]+nums[right];
                if (sum==0){
                    List<Integer> list = new ArrayList<>();
                    list.add(cur);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    lists.add(list);
                    while (left<right&&nums[left]==nums[left+1]) ++left;//去重
                    while (left<right&&nums[right]==nums[right-1]) --right;//去重
                    ++left;
                    --right;
                }else if (sum<0){
                    ++left;
                }else {
                    --right;
                }
            }
        }
        return lists;
    }
    public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);//排序
        int len=nums.length;
        //特殊情况
        if (len<3){
            return 0;
        }
        int sum=nums[0]+nums[1]+nums[2];//初始化值
        for (int i = 0; i < len; i++) {
            int left=i+1;
            int right=len-1;
            while (left<right){
                int cur=nums[left]+nums[i]+nums[right];
                //新知识：math.abs() 返回绝对值
                if (Math.abs(cur-target)<Math.abs(sum-target)){
                    sum=cur;
                }else if (cur>target){
                    right--;
                }else {
                    left++;
                }
            }
        }
        return sum;
    }
}
